home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / xulrunner / python / test / feedtest.py < prev    next >
Encoding:
Python Source  |  2007-11-12  |  12.2 KB  |  288 lines

  1. import unittest
  2. from tempfile import mkstemp
  3. from time import sleep
  4.  
  5. import config
  6. import prefs
  7. import dialogs
  8. import database
  9. from feed import validateFeedURL, normalizeFeedURL, Feed
  10.  
  11. from test.framework import DemocracyTestCase, EventLoopTest
  12.  
  13. class FakeDownloader:
  14.     pass
  15.  
  16. class AcceptScrapeTestDelegate:
  17.     def __init__(self):
  18.         self.calls = 0
  19.  
  20.     def runDialog(self, dialog):
  21.         self.calls += 1
  22.         if not isinstance(dialog, dialogs.ChoiceDialog):
  23.             raise AssertionError("Only expected ChoiceDialogs")
  24.         if not dialog.title.startswith("Channel is not compatible"):
  25.             raise AssertionError("Only expected scrape dialogs")
  26.         dialog.choice = dialogs.BUTTON_YES
  27.         dialog.callback(dialog)
  28.  
  29. class FeedURLValidationTest(DemocracyTestCase):
  30.     def test(self):
  31.         self.assertEqual(validateFeedURL(u"http://foo.bar.com/"), True)
  32.         self.assertEqual(validateFeedURL(u"https://foo.bar.com/"), True)
  33.                          
  34.         self.assertEqual(validateFeedURL(u"feed://foo.bar.com/"), False)
  35.         self.assertEqual(validateFeedURL(u"http://foo.bar.com"), False)
  36.         self.assertEqual(validateFeedURL(u"http:foo.bar.com/"), False)
  37.         self.assertEqual(validateFeedURL(u"https:foo.bar.com/"), False)
  38.         self.assertEqual(validateFeedURL(u"feed:foo.bar.com/"), False)
  39.         self.assertEqual(validateFeedURL(u"http:/foo.bar.com/"), False)
  40.         self.assertEqual(validateFeedURL(u"https:/foo.bar.com/"), False)
  41.         self.assertEqual(validateFeedURL(u"feed:/foo.bar.com/"), False)
  42.         self.assertEqual(validateFeedURL(u"http:///foo.bar.com/"), False)
  43.         self.assertEqual(validateFeedURL(u"https:///foo.bar.com/"), False)
  44.         self.assertEqual(validateFeedURL(u"feed:///foo.bar.com/"), False)
  45.  
  46.         self.assertEqual(validateFeedURL(u"foo.bar.com"), False)
  47.         self.assertEqual(validateFeedURL(u"crap:foo.bar.com"), False)
  48.         self.assertEqual(validateFeedURL(u"crap:/foo.bar.com"), False)
  49.         self.assertEqual(validateFeedURL(u"crap://foo.bar.com"), False)
  50.         self.assertEqual(validateFeedURL(u"crap:///foo.bar.com"), False)
  51.  
  52. class FeedURLNormalizationTest(DemocracyTestCase):
  53.     def test(self):
  54.         self.assertEqual(normalizeFeedURL(u"http://foo.bar.com"), u"http://foo.bar.com/")
  55.         self.assertEqual(normalizeFeedURL(u"https://foo.bar.com"), u"https://foo.bar.com/")
  56.         self.assertEqual(normalizeFeedURL(u"feed://foo.bar.com"), u"http://foo.bar.com/")
  57.  
  58.         self.assertEqual(normalizeFeedURL(u"http:foo.bar.com"), u"http://foo.bar.com/")
  59.         self.assertEqual(normalizeFeedURL(u"https:foo.bar.com"), u"https://foo.bar.com/")
  60.         self.assertEqual(normalizeFeedURL(u"feed:foo.bar.com"), u"http://foo.bar.com/")
  61.         self.assertEqual(normalizeFeedURL(u"http:/foo.bar.com"), u"http://foo.bar.com/")
  62.         self.assertEqual(normalizeFeedURL(u"https:/foo.bar.com"), u"https://foo.bar.com/")
  63.         self.assertEqual(normalizeFeedURL(u"feed:/foo.bar.com"), u"http://foo.bar.com/")
  64.         self.assertEqual(normalizeFeedURL(u"http:///foo.bar.com"), u"http://foo.bar.com/")
  65.         self.assertEqual(normalizeFeedURL(u"https:///foo.bar.com"), u"https://foo.bar.com/")
  66.         self.assertEqual(normalizeFeedURL(u"feed:///foo.bar.com"), u"http://foo.bar.com/")
  67.  
  68.         self.assertEqual(normalizeFeedURL(u"foo.bar.com"), u"http://foo.bar.com/")
  69.  
  70. class FeedTestCase(EventLoopTest):
  71.     def setUp(self):
  72.         EventLoopTest.setUp(self)
  73.         self.everything = database.defaultDatabase
  74.         [handle, self.filename] = mkstemp(".xml")
  75.  
  76.     def writefile(self, content):
  77.         self.url = u'file://%s' % self.filename
  78.         handle = file(self.filename,"wb")
  79.         # RSS 2.0 example feed
  80.         # http://cyber.law.harvard.edu/blogs/gems/tech/rss2sample.xml
  81.         handle.write(content)
  82.         handle.close()
  83.  
  84.     def makeFeed(self):
  85.         feed = Feed(self.url)
  86.         self.updateFeed(feed)
  87.         return feed
  88.  
  89.     def updateFeed(self, feed):
  90.         feed.update()
  91.         self.processThreads()
  92.         self.processIdles()
  93.  
  94. class SimpleFeedTestCase(FeedTestCase):
  95.     def setUp(self):
  96.         FeedTestCase.setUp(self)
  97.         # Based on 
  98.         # http://cyber.law.harvard.edu/blogs/gems/tech/rss2sample.xml
  99.  
  100.         # this rss feed has no enclosures.
  101.         self.writefile("""<?xml version="1.0"?>
  102. <rss version="2.0">
  103.    <channel>
  104.       <title>Liftoff News</title>
  105.       <link>http://liftoff.msfc.nasa.gov/</link>
  106.       <description>Liftoff to Space Exploration.</description>
  107.       <language>en-us</language>
  108.       <pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate>
  109.  
  110.       <lastBuildDate>Tue, 10 Jun 2003 09:41:01 GMT</lastBuildDate>
  111.       <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  112.       <generator>Weblog Editor 2.0</generator>
  113.       <managingEditor>editor@example.com</managingEditor>
  114.       <webMaster>webmaster@example.com</webMaster>
  115.       <item>
  116.          <title>Star City</title>
  117.          <link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.mov</link>
  118.          <description>How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's <a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm">Star City</a>.</description>
  119.          <pubDate>Tue, 03 Jun 2003 09:39:21 GMT</pubDate>
  120.          <guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid>
  121.       </item>
  122.       <item>
  123.          <description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a <a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm">partial eclipse of the Sun</a> on Saturday, May 31st.</description>
  124.          <pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate>
  125.          <guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid>
  126.       </item>
  127.       <item>
  128.          <title>The Engine That Does More</title>
  129.          <link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link>
  130.          <description>Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly.  The proposed VASIMR engine would do that.</description>
  131.          <pubDate>Tue, 27 May 2003 08:37:32 GMT</pubDate>
  132.          <guid>http://liftoff.msfc.nasa.gov/2003/05/27.html#item571</guid>
  133.       </item>
  134.       <item>
  135.          <title>Astronauts' Dirty Laundry</title>
  136.          <link>http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp</link>
  137.          <description>Compared to earlier spacecraft, the International Space Station has many luxuries, but laundry facilities are not one of them.  Instead, astronauts have other options.</description>
  138.          <pubDate>Tue, 20 May 2003 08:56:02 GMT</pubDate>
  139.          <guid>http://liftoff.msfc.nasa.gov/2003/05/20.html#item570</guid>
  140.       </item>
  141.    </channel>
  142. </rss>""")
  143.     def testRun(self):
  144.         dialogs.delegate = AcceptScrapeTestDelegate()
  145.         myFeed = self.makeFeed()
  146.  
  147.         # the feed has no enclosures, but we now insert enclosures into it.
  148.         # thus it should not cause a dialog to pop up and ask the user if they
  149.         # want to scrape.
  150.         self.assertEqual(dialogs.delegate.calls, 0)
  151.         self.assertEqual(self.everything.len(), 2) 
  152.  
  153.         # the Feed, plus the 1 item that is a video
  154.         items = self.everything.filter(lambda x:x.__class__.__name__ == 'Item')
  155.         self.assertEqual(items.len(), 1)
  156.  
  157.         # make sure that re-updating doesn't re-create the items
  158.         myFeed.update()
  159.         self.assertEqual(self.everything.len(), 2)
  160.         items = self.everything.filter(lambda x:x.__class__.__name__ == 'Item')
  161.         self.assertEqual(items.len(), 1)
  162.         myFeed.remove()
  163.  
  164. class EnclosureFeedTestCase(FeedTestCase):
  165.     def setUp(self):
  166.         FeedTestCase.setUp(self)
  167.         self.writefile("""<?xml version="1.0"?>
  168. <rss version="2.0">
  169.    <channel>
  170.       <title>Downhill Battle Pics</title>
  171.       <link>http://downhillbattle.org/</link>
  172.       <description>Downhill Battle is a non-profit organization working to support participatory culture and build a fairer music industry.</description>
  173.       <pubDate>Wed, 16 Mar 2005 12:03:42 EST</pubDate>
  174.       <item>
  175.          <title>Bumper Sticker</title>
  176.          <enclosure url="http://downhillbattle.org/key/gallery/chriscA.mpg" />
  177.          <description>I'm a musician and I support filesharing.</description>
  178.  
  179.       </item>
  180.       <item>
  181.          <title>T-shirt</title>
  182.          <enclosure url="http://downhillbattle.org/key/gallery/payola_tshirt.mpg" />
  183.       </item>
  184.       <item>
  185.          <enclosure url="http://downhillbattle.org/key/gallery/chriscE.mpg" />
  186.          <description>Flyer in Yucaipa, CA</description>
  187.       </item>
  188.       <item>
  189.          <enclosure url="http://downhillbattle.org/key/gallery/jalabel_nov28.mpg" />
  190.       </item>
  191.       <item>
  192.          <enclosure url="http://downhillbattle.org/key/gallery/jalabel_nov28.jpg" />
  193.       </item>
  194.       
  195.    </channel>
  196. </rss>""")
  197.     def testRun(self):
  198.         myFeed = self.makeFeed()
  199.         self.assertEqual(self.everything.len(),5)
  200.         items = self.everything.filter(lambda x:x.__class__.__name__ == 'Item')
  201.         self.assertEqual(items.len(),4)
  202.         #Make sure that re-updating doesn't re-create the items
  203.         myFeed.update()
  204.         self.assertEqual(self.everything.len(),5)
  205.         items = self.everything.filter(lambda x:x.__class__.__name__ == 'Item')
  206.         self.assertEqual(items.len(),4)
  207.         for item in items:
  208.             #Generate an exception if we didn't get one of the enclosures
  209.             item.entry["enclosures"][0]
  210.             self.assertRaises(IndexError,lambda :item.entry["enclosures"][1])
  211.         myFeed.remove()
  212.  
  213. class OldItemExpireTest(FeedTestCase):
  214.     # Test that old items expire when the feed gets too big
  215.     def setUp(self):
  216.         FeedTestCase.setUp(self)
  217.         self.counter = 0
  218.         self.writeNewFeed()
  219.         self.feed = self.makeFeed()
  220.         self.items = self.everything.filter(lambda x:x.__class__.__name__ == 'Item')
  221.         config.set(prefs.TRUNCATE_CHANNEL_AFTER_X_ITEMS, 4)
  222.  
  223.     def writeNewFeed(self, entryCount=2):
  224.         # make a feed with a new item and parse it
  225.         items = []
  226.         for x in range(entryCount):
  227.             self.counter += 1
  228.  
  229.             items.append("""\
  230. <item>
  231.  <title>Bumper Sticker</title>
  232.  <guid>guid-%s</guid>
  233.  <enclosure url="http://downhillbattle.org/key/gallery/%s.mpg" />
  234.  <description>I'm a musician and I support filesharing.</description>
  235. </item>
  236. """ % (self.counter, self.counter))
  237.  
  238.         self.writefile("""<?xml version="1.0"?>
  239. <rss version="2.0">
  240.    <channel>
  241.       <title>Downhill Battle Pics</title>
  242.       <link>http://downhillbattle.org/</link>
  243.       <description>Downhill Battle is a non-profit organization working to support participatory culture and build a fairer music industry.</description>
  244.       <pubDate>Wed, 16 Mar 2005 12:03:42 EST</pubDate>
  245.       %s
  246.    </channel>
  247. </rss>""" % '\n'.join(items))
  248.  
  249.     def checkGuids(self, *ids):
  250.         actual = set()
  251.         for i in self.items:
  252.             actual.add(i.getRSSID())
  253.         correct = set(['guid-%d' % i for i in ids])
  254.         self.assertEquals(actual, correct)
  255.  
  256.     def parseNewFeed(self, entryCount=2):
  257.         self.writeNewFeed(entryCount)
  258.         self.updateFeed(self.feed)
  259.  
  260.     def testSimpleOverflow(self):
  261.         self.assertEqual(self.items.len(), 2)
  262.         self.parseNewFeed()
  263.         self.assertEqual(self.items.len(), 4)
  264.         self.parseNewFeed()
  265.         self.assertEqual(self.items.len(), 4)
  266.         self.checkGuids(3, 4, 5, 6)
  267.  
  268.     def testOverflowWithDownloads(self):
  269.         self.items[0].downloader = FakeDownloader()
  270.         self.items[1].downloader = FakeDownloader()
  271.         self.assertEqual(self.items.len(), 2)
  272.         self.parseNewFeed()
  273.         self.parseNewFeed()
  274.         self.checkGuids(1, 2, 5, 6)
  275.  
  276.     def testOverflowStillInFeed(self):
  277.         self.parseNewFeed(6)
  278.         self.checkGuids(3, 4, 5, 6, 7, 8)
  279.  
  280.     def testOverflowWithReplacement(self):
  281.         # Keep item with guid-2 in the feed.
  282.         self.counter = 1
  283.         self.parseNewFeed(5)
  284.         self.checkGuids(2, 3, 4, 5, 6)
  285.  
  286. if __name__ == "__main__":
  287.     unittest.main()
  288.